# -*- coding:UTF-8 -*-

from __future__ import unicode_literals
import sys
import os
import time
import requests
import json
import hashlib
import pyaes
import traceback
import _thread
from os import path
from tkinter import *
from tkinter import ttk
from tkinter.filedialog import *
from binascii import a2b_hex, b2a_hex

from xiao.common import *
from xiao.logutil import *
from xiao.rwexcel import *
from xiao.message import *
from conf.settings import *

global log
log = LoggerUtil()

'''
主类，程序入口
# @author bricker
'''
class main():

    # 构造函数
    def __init__(self, root):
        global log
        self.log = log
        self.root = root
        self.uploadFile = None
        title = u'淘宝网店电子书上传工具', version
        root.title(title)
        root.resizable(False, False)
        root.geometry('%dx%s'%(window_height, window_width))
        self.layout()
        self.outLog(title, 0)
        self.url = settings.getUrl()
        self.taobaoUserId = settings.getTaobaoUserId()
        self.token = settings.getToken()
        self.key = settings.getKey()
        self.encryptType = settings.getEncryptType()
        self.encryptParam = settings.getEncryptParam()
        self.outLog('url=%s' % url, 0)
        self.outLog('taobaoUserId=%s' % taobaoUserId, 0)
        self.outLog('token=%s' % token, 0)
        self.outLog('key=%s' % key, 0)
        self.outLog('encryptType=%s' % encryptType, 0)
        self.outLog('encryptParam=%s' % encryptParam, 0)

    # 窗体布局函数
    def layout(self):
        # 添加框架
        f1 = Frame(self.root)
        f1.pack(fill = X, padx = 10, pady = 5)
        Label(f1, text = '文件路径:').pack(side = LEFT, anchor = 'n')
        self.filePathTx = StringVar()
        filePathEn = Entry(f1, textvariable = self.filePathTx, state = 'readonly')
        filePathEn.pack(side = LEFT, anchor = 'n')
        # 选择文件按钮
        chooseFileBtn = Button(f1, text = '选择文件', command = self.chooseFile)
        chooseFileBtn.pack(side = LEFT, anchor = 'n')

        Label(f1, text='最大同时上传数量:').pack(side = LEFT, anchor = 'n')

        uploadNumCo = ttk.Combobox(f1, width=5)
        uploadNumCo.pack(side = LEFT, anchor = 'n', padx = 5)
        uploadNumCo['values'] = ('1', '5', '10', '20', '50','~')
        uploadNumCo.current(0)
        self.uploadNumCo = uploadNumCo
        # 上传按钮
        Button(f1, text='Go!', command=self.handle).pack(side=LEFT, anchor='n')

        f2 = Frame(self.root)
        f2.pack(fill=X, padx=10, pady=5)
        scroll = Scrollbar(f2)
        scroll.pack(side = RIGHT, fill = Y)
        # log输出按钮
        outLogTx = Text(f2)
        # 设置Text控件只读
        outLogTx.bind("<KeyPress>", lambda e:"break")
        outLogTx.pack(side = RIGHT, fill = Y)
        scroll.config(command = outLogTx.yview)
        outLogTx.config(yscrollcommand = scroll.set)
        self.outLogTx = outLogTx

    # 选择文件函数
    def chooseFile(self):
        name = askopenfilename(filetypes = [('Excel文件', '*.xlsx')])
        self.filePathTx.set(name)
        self.uploadFile = name
        self.log.debug('选择文件:%s'%name)

    def handle(self):
        try:
            if not self.uploadFile:
                self.outLog('请先选择文件!!!')
            elif not path.exists(self.uploadFile):
                self.outLog('文件不存在!!!')
            elif path.isdir(self.uploadFile):
                self.outLog('请选择文件!!!')
            else:
                self.outLog('开始读取文件...')
                self.log.debug('读取文件:%s'%self.uploadFile)
                rw = rwexcel(self.uploadFile)
                msg = rw.read()
                if msg:
                    if msg.code == ErrorCode.c.SUCCESS:
                        self.outLog('文件读取成功!')
                        data = msg.obj
                        self.outLog('共需上传记录%d条'%len(data))
                        if len(data) > 0:
                            self.upload(data)
                    else:
                        self.outLog('文件读取失败[%s]!!!'%msg.msg)
                else:
                    self.outLog('文件读取失败!!!')
        except:
            exc = traceback.format_exc()
            log.error('开始上传异常', exc)
            self.outLog('“Go!”执行出现异常！！！')

    def upload(self, datas):
        self.outLog('开始上传数据...')
        uploadNum = self.uploadNumCo.get()
        self.outLog('同时上传数量:%s' % (uploadNum))
        length = len(datas)
        postArr = []
        postBookNameArr = []
        count = 0
        for data in datas:
            self.log.debug(data)

            postArr.append(data)
            count += 1
            bookName = data['productInfo']['bookName']
            postBookNameArr.append(bookName)

            if (uploadNum == '~' or len(postArr) < int(uploadNum)) and count < length:
                continue

            m = self.post(postArr)
            if m.code == ErrorCode.c.SUCCESS:
                j = json.loads(m.msg)
                if j['status'] == 200:
                    self.outLog('%s上传成功'%postBookNameArr)
                else:
                    self.outLog('%s上传失败[%s]'%(postBookNameArr, m.msg))
            else:
                self.outLog('%s上传出现错误[status:%d, msg:%s]'% (postBookNameArr, m.code, m.msg))
            self.outLog('%s上传处理完成' % (postBookNameArr))
            postArr.clear()
            postBookNameArr.clear()


    def post(self, books):
        url = self.url
        data = {}
        data['metaInfos'] = books
        data['taobaoUserId'] = self.taobaoUserId
        data['token'] = self.token
        dataStr = json.dumps(data, ensure_ascii = False)
        sign = self.MD5(dataStr + key)
        if encryptType == '2':
            dataStr = self.AES_encrypt(sign, dataStr)
        params = {}
        params['data'] = dataStr
        params['encryptType'] = encryptType
        params['sign'] = sign
        params['encryptParam'] = encryptParam
        self.log.debug('url:%s, params:%s'%(url, params))
        r = requests.post(url, data = params)
        self.log.debug('status:%s, message:%s'%(r.status_code, r.text))
        m = Message()
        if r.status_code == 200:
            m.code = ErrorCode.c.SUCCESS
            m.msg = r.text
        else:
            m.code = r.status_code
            m.msg = r.text
        return m
    def MD5(self, text):
        hl = hashlib.md5()
        hl.update(text.encode(encoding = default_conding))
        return hl.hexdigest()

    def AES_encrypt(self, key, text):
        byte = text.encode('utf-8')
        aes = pyaes.AESModeOfOperationCTR(key.encode(encoding = default_conding))
        return bytes.decode(b2a_hex(aes.encrypt(byte)))

    def AES_decrypt(self, key, text):
        aes = pyaes.AESModeOfOperationCTR(key.encode(encoding = default_conding))
        return bytes.decode(aes.decrypt(a2b_hex(text)))

    def outLog(self, text, wait = 0.5):
        self.outLogTx.insert(END, text)
        self.outLogTx.insert(END, '\n')
        # 实时输出记录
        self.outLogTx.update()
        # 总是显示最底端文字
        self.outLogTx.see(END)
        print(text)
        self.log.debug(text)
        time.sleep(wait)

# 程序入口
if __name__ == '__main__':
    log.debug('******************************程序开始运行******************************')
    try:
        tk = Tk()
        m = main(tk)
        tk.mainloop()
    except:
        exc = traceback.format_exc()
        log.error('程序异常', exc)
    finally:
        log.debug('******************************程序运行结束******************************')
